home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Apple II Magazines (PO)
/
Nibble Volume 13, No. 01 (1992-01)(MindCraft Publishing)(Side A).zip
/
Nibble Volume 13, No. 01 (1992-01)(MindCraft Publishing)(Side A).po
/
SCREEN.CMD.S
< prev
next >
Wrap
Text File
|
1996-12-24
|
20KB
|
594 lines
********************************
* SCREEN.CMD.S *
* Screen Commander source code *
* by Paul Esser *
* *
* Copyright (C) 1991 by *
* MindCraft Publishing Corp. *
* Lincoln, MA 01773 *
* *
* EDASM assembler *
********************************
*------------------
* EQUATES
*------------------
* Filetypes used by TSAVE/TLOAD
*
SCR40TYPE EQU $F4 ;40-column TSAVE/TLOAD file type
SCR80TYPE EQU $F8 ;80-column " " " "
OURAUXID EQU $0400 ;Auxillary type for both of the above
*
* Zero page storage
*
PTR EQU $06 ;pointer ($6,7)
PADDR EQU $08 ;storage for address returned by GETBUFR
BAS1L EQU $06 ;temp storage for screen base address--
BAS1H EQU $07 ;(don't want to erase BASL/BASH at $28/29)
*
* Applesoft
*
HIMEM EQU $73 ;Applesoft HIMEM ($73,74)
*
* Keyboard/Screen
*
KEY EQU $C000 ;keyboard
STROBE EQU $C010 ;clear keyboard strobe
STORE80ON EQU $C001 ;use PAGE2 to switch between main/aux mem
RDCHARSET EQU $C01E ; >=$80: alternate charset (INV/MouseText)
RDCOL80 EQU $C01F ; >=$80: 80 column screen active
PAGE2OFF EQU $C054 ;select main memory (when STORE80 is ON)
PAGE2ON EQU $C055 ;select aux memory
*
* Monitor
*
CH EQU $24 ;horiz. position of cursor
OPLEN EQU $2F ;opcode length returned by CHKOPLEN
CSWL EQU $36 ;char output address
CSWH EQU $37
KSWL EQU $38 ;char input address
KSWH EQU $39
A1L EQU $3C ;Move start
A1H EQU $3D
A2L EQU $3E ;Move end
A2H EQU $3F
A4L EQU $42 ;Move destination
A4H EQU $43
INBUF EQU $200 ;input buffer, used for temp storage
CHKOPLEN EQU $F88E ;check opcode length
COUT EQU $FDED ;char output
MOVE EQU $FE2C ;Monitor Move routine
*
* BI Global Page
*
EXTRNCMD EQU $BE06 ;external command vector
ERROUT EQU $BE09 ;output BASIC.SYSTEM error
STATE EQU $BE42 ;nonzero: BASIC program is running
XTRNADDR EQU $BE50 ;external command address
XLEN EQU $BE52 ;external command length minus 1
XCNUM EQU $BE53 ;0 for external command
PBITS EQU $BE54 ;permitted parameter bits
FBITS EQU $BE56 ;found parameter bits
VPATH1 EQU $BE6C ;primary pathname or command name
GOSYSTEM EQU $BE70 ;do MLI call
CRACESS EQU $BEA3 ;CREATE access byte
CRFILID EQU $BEA4 ;CREATE file type
CRAUXID EQU $BEA5 ;CREATE auxillary type
CRFKIND EQU $BEA7 ;CREATE file storage type
SSGINFO EQU $BEB4 ;GET/SET FILE INFO parameter count
FIFILID EQU $BEB8 ;GET/SET FILE INFO file type
FIAUXID EQU $BEB9 ;GET/SET FILE INFO auxillary type
SREFNUM EQU $BEC7 ;GET/SET MARK or EOF reference number
OSYSBUF EQU $BECE ;OPEN system I/O buffer
OREFNUM EQU $BED0 ;OPEN returned reference number
RWREFNUM EQU $BED6 ;READ/WRITE reference num.
RWDATA EQU $BED7 ;READ/WRITE data location
RWCOUNT EQU $BED9 ;READ/WRITE amount of data
CFREFNUM EQU $BEDE ;CLOSE/FLUSH reference num.
GETBUFR EQU $BEF5 ;Allocate memory from BASIC.SYSTEM
*
* ProDOS Global Page
*
MACHID EQU $BF98 ;Machine ID
*
*--------------------
* INSTALLATION
*--------------------
ORG $4000
*
* Installation/Relocation segment
* by Bill Tudor
*
LDA #<PEND-PSTART+$100
JSR GETBUFR ;get memory above HIMEM
BCC GOTBUF
JMP ERROUT
GOTBUF STA PADDR ;save address of allocated memory space
STA MANUAL+1 ;manually relocate an opcode
LDA #>MODSTART
STA PTR ;set PTR to start of code that requires
LDA #<MODSTART ; modification
STA PTR+1
MODLOOP LDY #0
LDA (PTR),Y ;get an opcode
JSR CHKOPLEN ;find opcode length
LDY OPLEN
CPY #2 ;if it's not a 3-byte opcode (Y=2),
BNE NOMOD ; then no modification needed
LDA (PTR),Y
CMP #<PSTART ;see if opcode's high order byte is
BLT NOMOD ; within the program
CMP #<PEND+$100
BGE NOMOD ;if not, no modification needed
SEC
SBC #<PSTART ;if so, relocate it by subtracting
CLC ; current location then adding future
ADC PADDR ; location to high order byte
STA (PTR),Y
NOMOD TYA
SEC
ADC PTR ;increment pointer to next opcode
STA PTR
BCC CHKDONE
INC PTR+1
CHKDONE LDA PTR+1 ;see if end of modification section
CMP #<MODEND ; has been reached
BLT MODLOOP
LDA PTR
CMP #>MODEND ;if not, modify some more
BLT MODLOOP
*
LDA EXTRNCMD+1 ;link into external command chain
STA NXTCMD+1
LDA EXTRNCMD+2
STA NXTCMD+2
LDA #$00
STA EXTRNCMD+1
LDA PADDR
STA EXTRNCMD+2
*
LDA #>PSTART ;now move the code to the memory
STA A1L ; reserved for it using Monitor
LDA #<PSTART ; MOVE routine
STA A1H
LDA #>PEND
STA A2L
LDA #<PEND
STA A2H
LDA #$00
STA A4L
LDA PADDR
STA A4H
LDY #0
JSR MOVE
CLC
RTS
*
HEREL EQU >* ;fill with zeros up to next page
DS $100-HEREL,0
*
*---------------------
* COMMAND PARSING
*---------------------
*
PSTART EQU * ;start of installed portion of program
MODSTART CLD ;start of part that has to be modified
LDA VPATH1
STA PTR ;get pointer to command/pathname
LDA VPATH1+1 ; into page zero
STA PTR+1
LDY #0
CHKTSAVE INY ;check for TSAVE command
LDA (PTR),Y
CMP S.TSAVE,Y ;compare command with TSAVE
BNE NOTTSAVE ;if no match, not TSAVE
CPY S.TSAVE ;see if more characters to check
BLT CHKTSAVE
LDA #>J.TSAVE ;it is TSAVE: prepare to parse
LDX #%00000001 ;set PBITS for pathname required
JMP PARSE ;go parse it
NOTTSAVE LDY #0
CHKTLOAD INY ;if not TSAVE, let's see if it is TLOAD
LDA (PTR),Y
CMP S.TLOAD,Y
BNE NOTTLOAD
CPY S.TLOAD
BLT CHKTLOAD
LDA #>J.TLOAD ;it is TLOAD
LDX #%00010001 ;set PBITS for pathname optional
JMP PARSE ;go parse it
NOTTLOAD LDY #0
CHKDUMP INY ;if not TLOAD, our last try is DUMP
LDA (PTR),Y
CMP S.DUMP,Y
BNE NOTOURS ;we'll give up if it is not DUMP
CPY S.DUMP
BLT CHKDUMP
LDA #>J.DUMP ;it is DUMP
LDX #%00010001 ;set PBITS for pathname optional
*
PARSE DEY ;Set up for BASIC.SYSTEM to parse command
STY XLEN ;set XLEN to command length minus 1
LDY #0
STY XCNUM ;zero XCNUM to indicate external command
STA XTRNADDR ;point XTRNADDR to particular command
MANUAL LDA #$00 ;--modified by relocator
STA XTRNADDR+1
STX PBITS ;set PBITS according to particular command
LDX #%00000100
STX PBITS+1 ;set PBITS+1: S and D parameters allowed
CLC ;carry clear indicates command found
RTS
*
NOTOURS SEC ;carry set indicates not our command
NXTCMD JMP $0000 ;--modified to point to other ext. cmds.
*
*----------------------
* COMMAND HANDLERS
*----------------------
*
J.TSAVE JMP TSAVE ;jump table used for each command
J.TLOAD JMP TLOAD ; handler because relocator assumes all
J.DUMP JMP DUMP ; three commands start on same page
*
* TSAVE command handler
*
TSAVE JSR SCRMODE ;get screen mode (40 or 80 col.)
LDA FILETYPE
LDX #>OURAUXID
LDY #<OURAUXID ;create file using TSAVE/TLOAD filetype
JSR CREATE ; and auxillary type
BCC TSAVE1
CMP #$13 ;ignore "DUPLICATE FILE NAME" error, we'll
BNE ERROR ; just write on top of old file
TSAVE1 JSR GETFILE ;verify file and open it
BCS ERROR ;error exit
JSR RWSETUP ;set up R/W parms, start at top of screen
TSAVE2 JSR GETLINE ;get a text screen line into INBUF
LDA #$CB ;and write it to disk with MLI WRITE call
JSR GOSYSTEM
BCS ERROPEN ;close and exit if error
INC LINECOUNT ;move down to next screen line
LDA LINECOUNT
CMP #24 ;continue until all 24 screen lines done
BNE TSAVE2
LDA #$CF
JSR GOSYSTEM ;GET_MARK followed by SET_EOF:
BCS ERROPEN ; in case the file somehow started out
LDA #$D0 ; larger than needed for text screen,
JSR GOSYSTEM ; this cuts off unused portion of file
BCC CLOSE
*
ERROPEN PHA ;Error while file is open:
LDA #$CC ; save error code on stack and close file
JSR GOSYSTEM
PLA
ERROR SEC ;Error: return to BI with carry set
RTS ; and error code in A reg.
*
* TLOAD command handler
*
TLOAD LDA FBITS ;check bit 0 of FBITS to see if
AND #$01 ; a pathname was specified
BNE TLOAD1 ;if no pathname, do nothing, just return
CLC ; to BASIC with carry clear (no error)
RTS
TLOAD1 JSR SCRMODE ;get screen mode
JSR GETFILE ;verify file and open it
BCS ERROR ;error exit
JSR RWSETUP ;set up R/W parms, start at top of screen
TLOAD2 LDA #$CA ;read a screen line from disk into INBUF
JSR GOSYSTEM ; with MLI READ call
BCS ERROPEN
JSR PUTLINE ;and put it on the text screen
INC LINECOUNT
LDA LINECOUNT ;do all 24 screen lines this way
CMP #24
BNE TLOAD2
*
CLOSE LDA #$CC ;exit to BASIC via close
JMP GOSYSTEM
*
* DUMP command handler
*
DUMP JSR SCRMODE ;get screen mode
LDA FBITS
AND #$01 ;check FBITS to see if pathname specified,
BEQ PRDUMP ; if not then dump to printer
LDA #$04
STA FILETYPE ;create a text file (filetype = 4)
LDX #0 ; (auxillary type = 0, not a random-access
LDY #0 ; file)
JSR CREATE
BCS ERROR
JSR OPEN ;open file
BCS ERROR ;error exit
JSR RWSETUP ;set up R/W, start at top line
INC RWCOUNT ;add 1 to write count for carriage return
DUMP2 JSR GETLINASC ;get a screen line & convert to ASCII text
LDA #$CB ;then write it to disk
JSR GOSYSTEM
BCS ERROPEN
INC LINECOUNT
LDA LINECOUNT ;do 24 lines
CMP #24
BNE DUMP2
JMP CLOSE ;then close file
*
* Printer Dump
* by Robert Heath
*
PRDUMP LDA CSWL ;save current input/output device
PHA
LDA CSWH
PHA
LDA KSWL
PHA
LDA KSWH
PHA
LDA CH ;save current cursor location
PHA ; (CH is modified by printer card)
LDA PRINTER ;set output to printer slot
STA CSWH
LDA #0
STA CSWL
STA LINECOUNT ;start at top screen line
TAX
INIT LDA INITSTR,X ;first send init. string to printer card
BEQ PRLINE
JSR COUT
INX
BNE INIT
PRLINE LDA KEY ;check for ESC or Ctrl-C keys, exit
CMP #$9B ; if either pressed
BEQ ESC
CMP #$83
BEQ CTRLC
JSR GETLINASC ;get screen line, convert to ASCII text
LDX #0
PRLINE1 LDA INBUF,X ;then send it to printer
ORA #$80
JSR COUT
INX
CPX SCRWIDTH
BLT PRLINE1
BEQ PRLINE1 ;(carriage return included at end of line)
INC LINECOUNT
LDA LINECOUNT
CMP #24 ;do all 24 lines
BNE PRLINE
EXIT PLA ;then restore original I/O device
STA CH ;and I/O device
PLA
STA KSWH
PLA
STA KSWL
PLA
STA CSWH
PLA
STA CSWL
CLC ;indicate no error
RTS
*
CTRLC LDA STATE ;Ctrl-C or ESC: Abort printer dump.
BNE EXIT ;Usually clear keyboard, except when
ESC STA STROBE ; ctrl-c pressed within running BASIC
JMP EXIT ; program, so ctrl-c stops program as well
*
*
* SUBROUTINES USED BY COMMAND HANDLERS
*
* Get screen display mode (40/80 columns, primary/alternate char. set)
*
SCRMODE LSR CHARSET ;start by assuming 40-column mode and
LDX #SCR40TYPE ; primary character set until proven
LDY #40 ; otherwise
LDA MACHID
AND #%11100010 ;check for IIe/IIc/IIc+/IIgs and presence
CMP #%10100010 ; of 80-column card and 64K minimum,
BNE SM2 ; if not then must be 40 column mode
LDA RDCHARSET ;check for alternate character set
BPL SM1 ; (alt. set has inverse lowercase $60-7F)
SEC ; if so, set bit 7 of CHARSET flag
ROR CHARSET
SM1 LDA RDCOL80 ;check for 80 column mode
BPL SM2 ; if not, skip
STA STORE80ON ;The STORE80ON and PAGE2OFF soft switches
STA PAGE2OFF ; should be on already, but just in case..
LDX #SCR80TYPE ;It is 80 column mode
LDY #80
SM2 STX FILETYPE ;save FILETYPE and SCRWIDTH variables
STY SCRWIDTH ; according to screen mode (40/80)
RTS
*
* Create a file
*
CREATE STA CRFILID ;Areg = filetype desired
STX CRAUXID ;(Xlo,Yhi) = auxillary type desired
STY CRAUXID+1
LDA #1
STA CRFKIND ;make it standard file (not subdirectory)
LDA #$C3
STA CRACESS ;make it unlocked
LDA #$C0
JMP GOSYSTEM ;go create it
*
* Get a line from the screen and stuff it in INBUF
*
GETLINE JSR BAS1CALC ;get base address of current screen line
LDA SCRWIDTH
CMP #80 ;if 80 column mode, use GETLINE80
BEQ GETLINE80
LDY #39 ;40 column mode: copy 40 bytes from screen
GL1 LDA (BAS1L),Y ; base address to INBUF
STA INBUF,Y
DEY
BPL GL1
RTS
GETLINE80 LDX #79 ;80 column mode: alternate 40 main memory
LDY #39 ; bytes with 40 auxillary memory bytes
GL2 LDA (BAS1L),Y ; from screen base address, and put into
STA INBUF,X ; 80-byte area at INBUF
DEX
PHP
SEI ;(no interruptions when aux. memory on)
STA PAGE2ON
LDA (BAS1L),Y
STA INBUF,X ;Note: Auxillary memory bytes are in even
STA PAGE2OFF ; columns 0-78.
PLP ; Main memory bytes are in odd
DEX ; columns 1-79.
DEY
BPL GL2
RTS
*
* Get a line into INBUF and convert to ASCII characters $20-7E
*
GETLINASC JSR GETLINE ;First get the line into INBUF
LDX #0
GLA1 LDA INBUF,X ;get screen byte
BMI GLA2
BIT CHARSET ;if it is flashing ($40-7F, primary char.
BMI GLA2 ; set only), then convert it to
AND #$3F ; inverse ($00-3F)
GLA2 AND #$7F ;Clear high bit
CMP #$7F ;If del character $7F (checkerboard box),
BNE GLA3 ; convert it to a space ($20) because
LDA #$20 ; many printers can't print it
GLA3 CMP #$20 ;Convert $00-1F (inverse uppercase) to
BCS GLA4 ; ASCII uppercase ($40-5F)
ORA #$40
GLA4 STA INBUF,X ;store modified byte
INX
CPX SCRWIDTH ;do all 40 or 80 screen bytes in the line
BNE GLA1
LDA #$0D ;add a carriage return ($0D)
STA INBUF,X ; to the end of the line
RTS
*
* Put a line onto the screen from INBUF
*
PUTLINE JSR BAS1CALC ;Works same as GETLINE except it performs
LDA SCRWIDTH ; reverse action--moves INBUF to screen
CMP #80
BEQ PUTLINE80
LDY #39
PL1 LDA INBUF,Y
STA (BAS1L),Y
DEY
BPL PL1
RTS
PUTLINE80 LDX #79
LDY #39
PL2 LDA INBUF,X
STA (BAS1L),Y
DEX
PHP
SEI
STA PAGE2ON
LDA INBUF,X
STA (BAS1L),Y
STA PAGE2OFF
PLP
DEX
DEY
BPL PL2
RTS
*
* Calculate screen base address, given LINECOUNT = screen line count
*
BAS1CALC LDA LINECOUNT ;Given vtab (0-23), calculate screen base
PHA ; address
LSR A
AND #$03 ;Works same as Monitor routine BASCALC
ORA #$04 ; ($FBC1), except stores result in
STA BAS1H ; BAS1L,BAS1H ($6,7) instead of
PLA ; BASL,BASH ($28,29).
AND #$18
BCC BC1
ADC #$7F
BC1 STA BAS1L
ASL A
ASL A
ORA BAS1L
STA BAS1L
RTS
*
* Set up READ/WRITE parameters, and initialize LINECOUNT to 0 (top line)
*
RWSETUP LDA #>INBUF
STA RWDATA
LDA #<INBUF ;R/W data area is INBUF ($200)
STA RWDATA+1
LDA SCRWIDTH ;R/W count is 40 or 80 bytes depending
STA RWCOUNT ; on screen mode (40/80 columns)
LDA #0
STA RWCOUNT+1
STA LINECOUNT ;zero LINECOUNT to start at top line
RTS
*
* Get file info to make sure it is a screen file, then open it
*
GETFILE LDA #$0A ;set up GET_FILE_INFO parameter count
STA SSGINFO
LDA #$C4 ;do GET_FILE_INFO call
JSR GOSYSTEM
BCS GETERR ;exit if error
LDA FIFILID
CMP FILETYPE ;verify proper filetype ($F4 or $F8
BNE TYPEMIS ; depending on 40/80 column mode)
LDA FIAUXID ;if wrong type then "FILE TYPE MISMATCH"
CMP #>OURAUXID ; error will be reported
BNE TYPEMIS
LDA FIAUXID+1 ;also verify proper auxillary type ($0400)
CMP #<OURAUXID ;if filetype & auxtype OK, then
BNE TYPEMIS ; fall through to OPEN routine
*
* Open file
*
OPEN LDA HIMEM ;use general purpose I/O buffer at HIMEM
STA OSYSBUF ; for OPEN command
LDA HIMEM+1
STA OSYSBUF+1
LDA #$C8 ;do OPEN call
JSR GOSYSTEM
BCS GETERR ;exit if error
LDA OREFNUM
STA RWREFNUM ;copy reference number returned by OPEN
STA SREFNUM ; to R/W, EOF/MARK, and CLOSE/FLUSH
STA CFREFNUM ; parameter lists
CLC ;indicate no error
RTS
TYPEMIS LDA #$0D ;Type Mismatch error code
GETERR SEC ;indicate error occurred
RTS
*
*
MODEND EQU * ;everything following doesn't get modified
*
*
* CONSTANTS
*
MSB OFF ;ASCII characters now have high bit off
S.TSAVE STR 'TSAVE' ;Command strings (begin with length byte)
S.TLOAD STR 'TLOAD'
S.DUMP STR 'DUMP'
*
MSB ON ;ASCII characters now have high bit on
INITSTR DFB $8D,$8D,$89 ;Printer init string
ASC '82N' ; sets line length to 81 characters and
DFB $8D,$8D ;prints a few blank lins
DFB $8D,$8D,$00
*
PRINTER DFB $C1 ;printer slot: change to $Cn for slot n
*
*
* VARIABLE STORAGE
*
FILETYPE DFB 0 ;filetype expected by GETFILE routine
SCRWIDTH DFB 0 ;screen width: 40 or 80
CHARSET DFB 0 ;flag for primary/alt. char set (bit 7)
LINECOUNT DFB 0 ;vtab line count, vary from 0 to 23
*
PEND DFB 0 ;end of program
*